package com.meiqiang.agent.transform;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.lang.instrument.ClassFileTransformer;
import java.security.ProtectionDomain;

/**
 * @author : zhengmeiqiang
 * @date : 2024/11/8 13:39
 */
public class FruitTransformer implements ClassFileTransformer {

    /**
     * 因为addTransformer方法不能指明需要转换的类，所以需要通过className判断当前加载的class是否我们要拦截的目标class，
     * 对于非目标class直接返回原字节数组，注意className的格式，需要将类全限定名中的.替换为/
     * @param loader
     * @param className
     * @param classBeingRedefined
     * @param protectionDomain
     * @param classfileBuffer
     * @return
     */
    @Override
    public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined,
                            ProtectionDomain protectionDomain, byte[] classfileBuffer) {
        if (!className.equals("com/meiqiang/po/Fruit")) {
            return classfileBuffer;
        }

        String fileName = "D:\\idea_pj\\java-agent\\Fruit.class";
        return getClassBytes(fileName);
    }

    /**
     * 读取我们之前复制出来的class文件，读入二进制字符流，替换原有classfileBuffer字节数组并返回，完成class定义的替换
     * @param fileName
     * @return
     */
    public static byte[] getClassBytes(String fileName) {
        File file = new File(fileName);
        try (InputStream is = new FileInputStream(file);
             ByteArrayOutputStream bs = new ByteArrayOutputStream()) {
            long length = file.length();
            byte[] bytes = new byte[(int) length];

            int n;
            while ((n = is.read(bytes)) != -1) {
                bs.write(bytes, 0, n);
            }
            return bytes;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
}
